home *** CD-ROM | disk | FTP | other *** search
/ NetNews Offline 2 / NetNews Offline Volume 2.iso / news / comp / lang / c++-part2 / 14545 < prev    next >
Encoding:
Text File  |  1996-08-05  |  4.5 KB  |  145 lines

  1. Path: news.mcs.net!usenet
  2. From: mikey@mcs.com (Mike Young)
  3. Newsgroups: comp.lang.ada,comp.lang.c++
  4. Subject: Re: some questions re. Ada/GNAT from a C++/GCC user
  5. Date: 31 Mar 1996 09:28:09 GMT
  6. Organization: Fen Software, Inc.
  7. Message-ID: <4jlj79$h1k@Nntp1.mcs.net>
  8. References: <wnewmanDoxrCp.DKv@netcom.com> <Dp1oAw.7Cz@world.std.com>
  9. NNTP-Posting-Host: mikey.pr.mcs.net
  10. Mime-Version: 1.0
  11. Content-Type: Text/Plain; charset=US-ASCII
  12. X-Newsreader: WinVN 0.99.6
  13.  
  14. In article <Dp1oAw.7Cz@world.std.com>, bobduff@world.std.com says...
  15. >
  16. >In article <wnewmanDoxrCp.DKv@netcom.com>,
  17. >Bill Newman <wnewman@netcom.com> wrote:
  18. >
  19. >>...Is there any way of
  20. >> doing something like this in Ada?  (I imagine there is, since the
  21. >> alternatives look unnecessarily difficult to maintain.)
  22. >
  23. >I'll note that the alternatives I gave could be done in C++, too,
  24. >without macros.
  25.  
  26. ===========
  27. If you're interested, the STL in C++ can do precisely this.
  28.  
  29. template <class T, class S>
  30. class SumOf
  31. {
  32. public:
  33.   SumOf(S initial) : sum(initial);
  34.   void operator()(const T& t) { sum += t; } // T must be convertable to
  35.                                             // formal type S.
  36.   operator const S&()const { return sum; }  // SumOf<T,S> is itself
  37.                                             // convertable to type S.
  38. };
  39.  
  40. typedef list<Stuff> Basket;
  41. unsigned BasketTotal(const Basket & basket)
  42. {
  43.   SumOf<Stuff, unsigned> sum;
  44.   for_each(basket.begin(), basket.end(), sum);
  45.   return sum;
  46. }
  47.  
  48. This isn't saying anything new, except that the STL defines containers and 
  49. operations on containers in a generic way.
  50.  
  51.  
  52. >The usual thing is to write something like:
  53. >
  54. >    Put_Line("done with sampling, W = " & Image(W)
  55. >           & ", table = " & Image(Table));
  56. >
  57. >For simple data types, there is the 'Image attribute.  For others, you
  58. >have to write your own Image function, which converts it to a string.
  59. >You said you wanted to do that anyway.  If you don't like
  60. >Text_IO.Put_Line, write your own: Two procedures for each verbosity
  61. >level, and one of those two can add the new-line.  Or maybe you always
  62. >want a new-line.  Or maybe the verbosity should be passed as a
  63. >parameter, with a default.  I can imagine many variations.
  64. >
  65. >Some people go even further, and define overloaded versions of "&" that
  66. >do both the concatenation and the conversion-to-string.  Seems like
  67. >overkill to me, but some people like it.
  68.  
  69. ===========
  70. I'd been bemoaning the lack of iostreams in Ada. Would you elaborate (no pun 
  71. intended) more on how "&" and 'Image would be used? The common C++ idiom would 
  72. be something like this:
  73.  
  74. class Foo
  75. {
  76.    ...
  77. public:
  78.   ostream & Print(ostream &) const;
  79. };
  80. inline
  81. ostream & operator<<(ostream & os, const Foo & r)
  82. { return r.Print(os); }
  83.  
  84. void Fred(const Foo & foo)
  85. {
  86.   cout << "Done with sampling, " << foo << endl;
  87. }
  88.  
  89. void Barney(const list<Foo> & foo, ostream & os)
  90. {
  91.   os << "Done with sampling, " << foo.size() << " values:" << endl;
  92.   ostream_iterator<Foo> outStream(os, "\n");
  93.   copy(foo.begin(), foo.end(), outStream);
  94.   os << endl;
  95. }
  96.  
  97. >
  98. >You'll find a lot of anti-macro fanatics in the Ada world.
  99.  
  100. =======
  101. Likewise in C++. :)
  102.  
  103. >Macros are generally hard to understand for other reasons, I think.
  104.  
  105.   [... some worthy thoughts snipped ...]
  106. >
  107. >If you complain that you want macros to do For_Each, I'll answer by
  108. >giving you iterators, not by giving you macros.  Same for Write_Sequence
  109. >-- better to use a procedure call than a macro call, IMHO.
  110.  
  111. ============
  112. Yup. Good practice is not limited by choice of language, I see. :)
  113.  
  114. The other sad part of function-like macros is safety of side-effects in macro 
  115. arguments. Function arguments are evaluated once before calling; macros do god 
  116. knows what. A canonical example of badness is:
  117.  
  118. #define MatchChar(a,b) (putc(a==b?b:'_'))
  119. void foo()
  120. {
  121.   MatchChar('X', getc());
  122. }
  123.  
  124. If getc() were implemented as a macro, as it is on many systems, MatchChar 
  125. would print the character following the one being matched. This may or may not 
  126. be the desired result. Inline functions and templates generally make this a 
  127. thing of the past.
  128.  
  129. In spite of this, macros are still the only way to perform some useful tasks. 
  130. For example:
  131.  
  132. #ifndef _DEBUG
  133. #define assert(a)
  134. #else
  135. #define assert(a) {if (!a) {_assert_fail(__FILE__, __LINE__, #a);}}
  136. #endif
  137.  
  138. How would you do this in Ada? In particular, how would I express pre- and 
  139. post-conditions? The C macro grabs the filename and line number of the failure, 
  140. and prints out verbatim the test condition that failed. __FILE__ and __LINE__ 
  141. are themselves macros, evaluated at the point where assert is invoked.
  142.  
  143. Mike.
  144.  
  145.